package com.acmen.easyapi.generator;

import com.acmen.easyapi.annotation.Param;
import com.acmen.easyapi.util.AopTargetUtil;
import com.acmen.easyapi.util.SpringContextUtil;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.regex.Pattern;

/**
 * EL表达式数据获取器
 *
 * @author acmen
 * @date 2022-04-06
 */
@Component
public class ElDataGenerator implements DataGenerator {
    private final static String PATTERN = "^\\$\\{[\\s\\S]*(.[\\s\\S]*)*\\}$";

    @Override
    public boolean matches(Field field, Param param) {
        return Pattern.matches(PATTERN, param.testData());
    }

    @Override
    public Object generate(Field field, Param param) {
        return getValue(param.testData());
    }

    /**
     * 数据获取说明
     *
     * @return
     */
    @Override
    public String getNote() {
        String note = "EL表达式：";
        note += "当@ReqParam.testData为'${bean.xxx}'时调用bean.getXxx()或者bean.isXxx()或者bean.xxx()获取数据。";
        return note;
    }

      /**
     * 根据给定的测试数据获取对象的值
     * @param testData 测试数据，包含表达式"${"和"}"包围的需要获取的值的路径
     * @return 对象的值
     */
    public Object getValue(String testData) {
        String exp = testData.replace("${", "").replace("}", "").trim();  // 替换掉字符串中的"${"和"}"并去除两端的空格得到exp
        String beanName = exp.substring(0, exp.indexOf("."));  // 获取exp中第一个"."之前的部分作为bean的名称
        exp = exp.substring(exp.indexOf(".") + 1);  // 获取exp中第一个"."之后的部分作为剩余的表达式
        Object bean = SpringContextUtil.getBean(beanName);  // 根据bean的名称从Spring上下文中获取bean对象
        bean = AopTargetUtil.getTarget(bean);  // 获取bean的真实目标对象
        while (exp != null) {  // 循环处理剩余的表达式
            int idx = exp.indexOf(".");  // 查找exp中第一个"."的位置
            String methodName;
            if (idx > -1) {  // 如果找到了"."
                methodName = exp.substring(0, idx);  // 获取"."之前的部分作为方法名
                exp = exp.substring(idx + 1);  // 获取"."之后的部分作为剩余的表达式
            } else {  // 如果没有找到"."
                methodName = exp;  // 将exp作为方法名
                exp = null;  // 剩余的表达式为空
            }
            bean = getValueByName(bean, methodName);  // 调用getValueByName方法获取方法调用的结果，并将其赋值给bean
        }
        return bean;  // 返回最终得到的bean对象
    }


    public static Object getValueByName(Object object, String methodName) {
        if (object == null) {
            // 如果传入的对象为空，则返回空
            return null;
        }
        try {
            // 获取方法名的第一个字母并转为大写
            String firstLetter = methodName.substring(0, 1).toUpperCase();
            // 构造以 "get" 开头的方法名
            String getter = "get" + firstLetter + methodName.substring(1);
            // 获取对象的类中是否存在该 getter 方法
            Method method = object.getClass().getMethod(getter);
            // 调用 getter 方法获取值
            Object value = method.invoke(object);
            // 返回获取到的值
            return value;
        } catch (Exception e) {
            try {
                // 如果上面的 getter 方法不存在，则尝试以 "is" 开头的方法名
                String firstLetter = methodName.substring(0, 1).toUpperCase();
                String getter = "is" + firstLetter + methodName.substring(1);
                // 获取对象的类中是否存在该 getter 方法
                Method method = object.getClass().getMethod(getter);
                // 调用 getter 方法获取值
                Object value = method.invoke(object);
                // 返回获取到的值
                return value;
            } catch (Exception e1) {
                try {
                    // 如果上面的 getter 方法也不存在，则尝试直接调用方法名
                    Method method = object.getClass().getMethod(methodName);
                    // 调用方法获取值
                    Object value = method.invoke(object);
                    // 返回获取到的值
                    return value;
                } catch (Exception e2) {
                    // 如果就连最后一搏的方法也不行，则返回空字符串
                    return "";
                }
            }
        }

    }

}
